package com.example.android.plugin.host;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.xmlpull.v1.XmlPullParserException;

import com.example.android.plugin.framework.PluginBuilder;
import com.example.android.plugin.framework.PluginDescription;
import com.example.android.plugin.framework.PluginInvoke;
import com.example.android.plugin.framework.PluginSearch;
import com.example.android.plugin.framework.beans.Plugin;
import com.example.android.plugin.framework.beans.PluginFeatureBean;
import com.example.android.plugin.framework.beans.PluginFeatureMethod;
import com.example.android.plugin.framework.beans.PluginIntent;
import com.example.android.plugin.framework.util.Description;
import com.example.android.plugin.host.descriptions.MainDescription;
import com.example.android.plugin.host.descriptions.SkinDescription;
import com.example.android.plugin.host.interfaces.Skin;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends Activity {

	private LinearLayout pluginList;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		pluginList = (LinearLayout) this
				.findViewById(R.id.main_plugin_items_list);
		
		Button button = (Button) this.findViewById(R.id.button_refresh);
		button.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v) {
				refresh();
			}
		});
		refresh();
	}

	public void refresh() {
		pluginList.removeAllViews();
		
		try {
			listPlugins();
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (XmlPullParserException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}

		// 没有可用插件时显示提示
		if (pluginList.getChildCount() <= 0) {
			TextView tv = new TextView(this);
			tv.setText("现在没有可用的插件");
			pluginList.addView(tv);
		}
	}

	/**
	 * 发现并列出插件
	 * 
	 * @throws XmlPullParserException
	 * @throws IOException
	 * @throws NameNotFoundException
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 */
	private void listPlugins() throws NameNotFoundException, IOException,
			XmlPullParserException, ClassNotFoundException,
			IllegalAccessException, InstantiationException,
			IllegalArgumentException, SecurityException, NoSuchFieldException {
		
		// 首先，就是查找插件
		PluginSearch psearch = new PluginSearch();
		List<Plugin> plugins = psearch.getPlugins(this);

		// 把插件信息组装到plugins里面
		PluginBuilder pbuilder = new PluginBuilder(this);
		plugins = pbuilder.buildPluginsDescrition(plugins);

		for (final Plugin plugin : plugins) {
			// 加入插件
			PluginItem item = new PluginItem(this,
					plugin.getPkgInfo().packageName);

			// 根据item类型，选择处理方式
			@SuppressWarnings("unchecked")
			Class<? extends Description> pluginType = (Class<? extends Description>) Class
					.forName(plugin.getSuperDescription());
			if (pluginType.equals(MainDescription.class)) {
				item = getDefaultItem(plugin, item);
			} else if (pluginType.equals(SkinDescription.class)) {
				item = getSkinItem(plugin, item);
			}

			// 将插件加入展示
			pluginList.addView(item);
		}
	}

	/**
	 * 皮肤插件处理方式
	 * 
	 * @param plugin
	 * @param item
	 * @return
	 * @throws ClassNotFoundException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws NameNotFoundException
	 * @throws IllegalArgumentException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	private PluginItem getSkinItem(final Plugin plugin, PluginItem item)
			throws ClassNotFoundException, IllegalAccessException,
			InstantiationException, NameNotFoundException,
			IllegalArgumentException, SecurityException, NoSuchFieldException {

		// 获取插件的描述对象
		PluginDescription<SkinDescription> pdes = new PluginDescription<SkinDescription>(
				SkinDescription.class);
		SkinDescription des = pdes.getDescription(this, plugin);

		// 设置插件item的描述信息
		item.setDescription(des.getDescription());
		item.setTitle(des.getSubTitle());

		Drawable drawable = plugin.getContext().getResources()
				.getDrawable(des.getIconResId());
		item.setIconImage(drawable);

		// 获得当前插件的功能
		List<PluginFeatureBean> features = plugin.getFeatures();

		// 遍历功能
		for (final PluginFeatureBean pf : features) {
			for (final PluginFeatureMethod fm : pf.getMethods()) {

				// 添加插件，并且设置执行事件
				item.addPluginMethod(fm, new OnClickListener() {
					@Override
					public void onClick(View v) {
						PluginInvoke pi = new PluginInvoke(MainActivity.this);
						try {
							Skin entity = (Skin) pi.invoke(plugin, pf, fm);
							SkinDescription sd = entity.getSkinDescription();

							// 设置颜色
							MainActivity.this.getWindow()
									.setBackgroundDrawable(
											new ColorDrawable(sd
													.getBackground()));
							int size = pluginList.getChildCount();
							PluginItem itm = null;
							for (int i = 0; i < size; i++) {
								itm = (PluginItem) pluginList.getChildAt(i);
								itm.setBackgroundColor(sd.getItemBackground());
								itm.getFeatures().setBackgroundColor(
										sd.getItemButtonBackground());
							}

							// refresh();
						} catch (SecurityException e) {
							e.printStackTrace();
						} catch (IllegalArgumentException e) {
							e.printStackTrace();
						} catch (NameNotFoundException e) {
							e.printStackTrace();
						} catch (ClassNotFoundException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (InstantiationException e) {
							e.printStackTrace();
						} catch (NoSuchMethodException e) {
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							e.printStackTrace();
						} catch (NoSuchFieldException e) {
							e.printStackTrace();
						}
					}
				});
			}
		}

		return item;
	}

	/**
	 * 默认的item处理方式
	 * 
	 * @param plugin
	 * @param item
	 * @return
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 * @throws IllegalArgumentException
	 * @throws NameNotFoundException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 */
	private PluginItem getDefaultItem(final Plugin plugin, PluginItem item)
			throws ClassNotFoundException, IllegalAccessException,
			InstantiationException, NameNotFoundException,
			IllegalArgumentException, SecurityException, NoSuchFieldException {

		// 获取插件的描述对象
		PluginDescription<MainDescription> pdes = new PluginDescription<MainDescription>(
				MainDescription.class);
		MainDescription des = pdes.getDescription(this, plugin);

		// 设置插件item的描述信息
		item.setDescription(des.getDescription());
		item.setTitle(des.getSubTitle());

		Drawable drawable = plugin.getContext().getResources()
				.getDrawable(des.getIconResId());
		item.setIconImage(drawable);

		// 获得当前插件的功能
		List<PluginFeatureBean> features = plugin.getFeatures();

		// 遍历功能
		for (final PluginFeatureBean pf : features) {
			for (final PluginFeatureMethod fm : pf.getMethods()) {

				// 添加插件，并且设置执行事件
				item.addPluginMethod(fm, new OnClickListener() {
					@Override
					public void onClick(View v) {
						PluginInvoke pi = new PluginInvoke(MainActivity.this);
						try {
							pi.invoke(plugin, pf, fm);
						} catch (SecurityException e) {
							e.printStackTrace();
						} catch (IllegalArgumentException e) {
							e.printStackTrace();
						} catch (NameNotFoundException e) {
							e.printStackTrace();
						} catch (ClassNotFoundException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (InstantiationException e) {
							e.printStackTrace();
						} catch (NoSuchMethodException e) {
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							e.printStackTrace();
						} catch (NoSuchFieldException e) {
							e.printStackTrace();
						}
					}
				});
			}
		}

		// 遍历intent
		Map<String, PluginIntent> intents = plugin.getIntents();

		Iterator<Map.Entry<String, PluginIntent>> iterator = intents.entrySet()
				.iterator();

		while (iterator.hasNext()) {
			final Map.Entry<String, PluginIntent> entry = iterator.next();
			item.addPluginMethod(entry.getValue(), new OnClickListener() {
				@Override
				public void onClick(View v) {
					PluginInvoke pi = new PluginInvoke(MainActivity.this);
					try {
						pi.invoke(plugin, entry.getValue());
					} catch (NameNotFoundException e) {
						e.printStackTrace();
					} catch (NoSuchFieldException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					}
				}
			});

		}

		return item;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// 当按下键盘上返回按钮，给出退出对话框
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			new AlertDialog.Builder(this)
					.setTitle(R.string.quit_title)
					.setMessage(R.string.quit_message)
					.setNegativeButton(R.string.cancel,
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.dismiss();
								}
							})
					.setPositiveButton(R.string.confirm,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int whichButton) {
									System.exit(0);
								}
							}).show();
			return true;
		} else {
			return super.onKeyDown(keyCode, event);
		}
	}
}
